package backend;

import java.util.ArrayList;
import java.text.DecimalFormat;

/**
 *
 * @author Christian Janke
 */
public class Routenplaner {
    
    private ArrayList<MapWay> strassen;
    private WeightedGraph graph;
    private Dijkstra dick;
    private MapNode start;
    private MapNode ziel;
    private ArrayList<MapNode> weg = new ArrayList<MapNode>();
    
    public Routenplaner(ArrayList<MapWay> strassen){
        this.strassen = strassen;
        this.graph = new WeightedGraph(this.strassen);
    }
    
    public void shortestWay(MapNode start, MapNode ziel){
        this.start = start;
        this.ziel = ziel;
        this.dick = new Dijkstra(this.graph, start, ziel);
        this.weg = this.dick.findPath(true);
    }
    
    public void fastestWay(MapNode start, MapNode ziel){
        this.start = start;
        this.ziel = ziel;
        this.dick = new Dijkstra(this.graph, start, ziel);
        this.weg =  this.dick.findPath(false);
    }
  
    
    /**Berechnet den gewuenschten Weg
     * 
     * @param s Start-Node
     * @param z Ziel-Node
     * @param shortest kuerzester = true, schnellster = false
     */
    public void findWay(MapNode s, MapNode z, boolean shortest){
        if (shortest)
            this.shortestWay(s, z);
        else
            this.fastestWay(s, z);
    }
    
    /**Zur Ausgabe der Strassennamen
     * 
     * @return Auf #name #laenge m fahren (#zeit s)
     */
    public String wegbeschreibung(){
        if (this.weg.isEmpty())                            //Wenn kein Weg berechnet wurde
            return null;                             
        String output = "Wegbeschreibung von: ";            //Ausgabe-String
        String StartName = "";
        if (this.start.getTag("name") != null) 
            StartName = this.start.getTag("name");
        else {
            for (MapEdge w: this.graph.getKanten()){
                if (this.start == w.getNode1())
                    StartName = w.getName();
                else if (this.start == w.getNode2())
                    StartName = w.getName();
            }
        }
        String ZielName = "";
        if (this.ziel.getTag("name") != null) 
            StartName = this.ziel.getTag("name");
        else {
            for (MapEdge w: this.graph.getKanten()){
                if (this.ziel == w.getNode1())
                    ZielName = w.getName();
                else if (this.ziel == w.getNode2())
                    ZielName = w.getName();
            }
        }
        output += StartName + " nach: " + ZielName + "\n";
        DecimalFormat df = new DecimalFormat( "0.00" );     //Format fuer Ausgabe der Zahlen
        ArrayList<MapEdge> tmpEdges = this.graph.getKanten();   //Laden alle moeglichen Kanten
        MapEdge currWay = null;                                    //aktuelle Kante
        Double currLength = 0.0;                                   //aktuelle Strecke
        Double currTime = 0.0;                                  //aktuelle Zeit
        Double totalLength = 0.0;                               //Gesamtstrecke
        Double totalTime = 0.0;                                 //Gesamtzeit
        for (int i = 1; i < this.weg.size(); i++){         //Durchgehen aller Knoten auf der Route
            MapNode node1 = this.weg.get(i-1);
            MapNode node2 = this.weg.get(i);
            for (MapEdge e: tmpEdges){                      //Durchgehen aller moeglichen Kanten
                if ((e.getNode1() == node1) && (e.getNode2() == node2)){
                    if (currWay == null){
                        currWay = e;
                        output += "Losfahren auf " + e.getName() + " (" + df.format(currLength) + "m und " + df.format(currTime) + "s)\n";
                    }
                    currLength += e.getLength();
                    currTime += e.getTime();
                    totalLength += e.getLength();
                    totalTime += e.getTime();
                    if (e.getName().equals(currWay.getName()) == false){
                        output += "Auf " + currWay.getName() + " " + df.format(currLength) + "m (etwa " + df.format(currTime) + "s) fahren. Insgesamt: " + df.format(totalLength) + "m und " + df.format(totalTime) + "s.\n" ;
                        currWay = e;
                        currLength = 0.0;
                        currTime = 0.0;
                        MapNode node0 = this.weg.get(i-2);
                        if (Punkt.winkel(node0.getKoords(), node1.getKoords()) < Punkt.winkel(node1.getKoords(), node2.getKoords()))
                            output += "Rechts ";
                        else
                            output += "Links ";
                        output += "abbiegen auf: " + e.getName() + "\n";
                    }
                    break;
                }
            }
        }
        output += "Ankunft bei: " + ZielName + " nach " + df.format(totalTime) + "s und einer Fahrstrecke von " + df.format(totalLength) + "m.";
        return output;
    }
    
    /**Gibt eine Liste der zu passierenden Nodes zurueck
     * 
     * @return Liste der Nodes zum Malen
     */
    public ArrayList<MapNode> nodeList(){
        return this.weg;
    }
}